package cn.tqfeiyang.smartadmin.commons.exception;

import cn.tqfeiyang.smartadmin.commons.response.ApiResult;
import cn.tqfeiyang.smartadmin.commons.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 全局异常处理
 *
 * @author tqfeiyang
 * @date 2021-4-13
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 全局异常处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Throwable.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult exceptionHandle(Throwable exception) {
        return handle(exception);
    }

    /**
     * 全局异常处理
     *
     * @param exception
     * @return
     */
    public static ApiResult handle(Throwable exception) {
        log.error(exception.getMessage(), exception);
        if (exception instanceof BusinessException) {
            //业务异常
            return ApiResult.failed(exception.getMessage(), exception);
        } else if (exception instanceof InternalException) {
            //内部异常
            return ApiResult.failed("系统内部错误", exception);
        } else if (exception instanceof MissingServletRequestParameterException) {
            //参数缺失
            return ApiResult.failed(ResultCode.ARG_MISSING, exception);
        } else if (exception instanceof HttpMessageNotReadableException) {
            //参数解析错误，可能是 RequestBody 为空，或者是不是 JSON 格式
            return ApiResult.failed("参数解析错误", exception);
        } else if (exception instanceof MethodArgumentNotValidException) {
            //参数校验错误，传入的参数不满足 Validation 规则
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) exception;
            BindingResult bindingResult = ex.getBindingResult();
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            FieldError fieldError = fieldErrors.get(0);
            String errorMessage = fieldError.getDefaultMessage();
            return ApiResult.failed(errorMessage, exception);
        } else if (exception instanceof MethodArgumentTypeMismatchException) {
            //参数类型错误
            MethodArgumentTypeMismatchException ex = (MethodArgumentTypeMismatchException) exception;
            return ApiResult.failed("参数类型错误(%s)".formatted(ex.getPropertyName()), exception);
        } else if (exception instanceof DuplicateKeyException) {
            return ApiResult.failed("数据违反唯一约束", exception);
        } else if (exception instanceof DataIntegrityViolationException) {
            return ApiResult.failed("数据完整性异常", exception);
        } else if (exception instanceof HttpRequestMethodNotSupportedException) {
            return ApiResult.failed(exception.getMessage(), exception);
        }
        return ApiResult.failed(exception.getMessage(), exception);
    }
}
